package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.Nullable;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Autowired
	private RabbitService rabbitService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private RedissonClient redissonClient;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
		/*	album_attribute_value
			album_info
			album_stat  --初始化一个随机初始值 页面统计信息太低肯呢个没有用户看*/


		/*album_info*/
		AlbumInfo albumInfo=new AlbumInfo();
		//给对象赋值
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		//设置用户id
		albumInfo.setUserId(userId);
		//根据album_info表中pay_type判断专辑付费类型来对应tracks_for_free可以免费试听的集数
		//若支付类型为不为免费则试听集数为5
		if (!albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)) {
			//设置免费试听集数为5
			albumInfo.setTracksForFree(5);
		}
		//status 专辑审核状态
 		albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);


		//保存数据
		albumInfoMapper.insert(albumInfo);

		/*album_attribute_value*/
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		if(!CollectionUtils.isEmpty(albumAttributeValueVoList)){
			//循环遍历
			for(AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList){
				//创建对象
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
				//赋值
				albumAttributeValue.setAlbumId(albumInfo.getId());
				albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
				albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
				//为了循环多次执行循环insert语句
				//可以优化为批量插入  减少循环
				albumAttributeValueMapper.insert(albumAttributeValue);
			}
		}

		/*album_stat*/

		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_PLAY);
		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_SUBSCRIBE);
		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_BROWSE);
		this.saveAlbumStat(albumInfo.getId(),SystemConstant.ALBUM_STAT_COMMENT);

	}

	public void saveAlbumStat(Long albumId, String statPlay) {
		//创建对象
		AlbumStat albumStat = new AlbumStat();
		//设置专辑id
		albumStat.setAlbumId(albumId);
		//设置统计类型
		albumStat.setStatType(statPlay);
		//设置一个100以内的随机数作为统计数目
		albumStat.setStatNum(new Random().nextInt(100));
		//保存
		albumStatMapper.insert(albumStat);
	}

	@Override
	public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> albumListVoPage, AlbumInfoQuery albumInfoQuery) {
		return albumInfoMapper.selectUserAlbumPage(albumListVoPage,albumInfoQuery);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeAlbumInfoById(Long albumId) {
		/*album_info
		album_attribute_value
		album_stat
		*/
		//逻辑删除
		//album_info
		albumInfoMapper.deleteById(albumId);
		//album_attribute_value
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
		//album_stat
		albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId,albumId));

	}

	@Override
	@GuiGuCache(prefix = "album:info:")
	public AlbumInfo getAlbumInfo(Long albumId) {
		//	1.	查询数据的时候，先查询缓存！
		//	定义一个缓存的key=album:info:albumId;
		//        AlbumInfo albumInfo = getByRedisson(albumId);
		//        if (albumInfo != null) return albumInfo;
		//  数据库兜底.
		return getInfoDB(albumId);

	}

	@Nullable
	private AlbumInfo getByRedisson(Long albumId) {
		String key = RedisConstant.ALBUM_INFO_PREFIX + albumId;
		try {
			//	什么情况下选中hash，或字符串！
			AlbumInfo albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(key);
			//	判断缓存中是否有数据
			if (null == albumInfo) {
				//	缓存中为空！查询数据库. 声明一个锁的key
				String locKey = RedisConstant.ALBUM_LOCK_SUFFIX + albumId;
				//	获取到锁对象。
				RLock lock = redissonClient.getLock(locKey);
				//	上锁
				lock.lock();
				try {
					//	查询数据库之前，再查询一次缓存.
					albumInfo = (AlbumInfo) this.redisTemplate.opsForValue().get(key);
					//	如何缓存中有数据直接返回.
					if (null != albumInfo) {
						return albumInfo;
					}
					//	业务逻辑
					albumInfo = this.getInfoDB(albumId);
					System.out.println("查询数据库");
					//	从数据库获取的数据值为空.
					if (null == albumInfo) {
						//	存储空对象
						this.redisTemplate.opsForValue().set(key, new AlbumInfo(), RedisConstant.ALBUM_TEMPORARY_TIMEOUT, TimeUnit.SECONDS);
						return new AlbumInfo();
					}
					//	将真实数据存储到缓存
					this.redisTemplate.opsForValue().set(key, albumInfo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.DAYS);
					return albumInfo;
				} catch (Exception e) {
					throw new RuntimeException(e);
				} finally {
					new ReentrantLock().unlock();
					//	解锁处理
					lock.unlock();
				}
			}else {
				System.out.println("走了缓存.");
				//  返回数据
				return albumInfo;
			}
		} catch (RuntimeException e) {
			//  sendMsg("服务器挂了.");
			log.error("出现了异常"+e.getMessage());
		}
		return null;
	}
	@Nullable
	private AlbumInfo getInfoDB(Long albumId) {
		//	获取专辑对象
		AlbumInfo albumInfo = this.getById(albumId);
		//	给专辑对象赋值标签集合数据
		if (null != albumInfo) {
			//	select * from album_attribute_value where album_id = ?;
			albumInfo.setAlbumAttributeValueVoList(albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId)));
		}
		//	返回数据
		return albumInfo;
	}

	@Override
	public void updateAlbumInfoById(Long albumId, AlbumInfoVo albumInfoVo) {
		/*
		* album_info
		* album_attribute_value
		*/
		//创建对象
		AlbumInfo albumInfo = new AlbumInfo();
		//album_info
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		albumInfo.setId(albumId);
		this.albumInfoMapper.updateById(albumInfo);

		//album_attribute_value
		//先将数据删除在新增
		this.albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
		//获取前端传来的属性值集合
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		//进行判断是否进行循环
		if(!CollectionUtils.isEmpty(albumAttributeValueVoList)){
			//循环遍历
			for(AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList){
				//创建对象
				AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
				//赋值
				albumAttributeValue.setAlbumId(albumInfo.getId());
				albumAttributeValue.setAttributeId(albumAttributeValueVo.getAttributeId());
				albumAttributeValue.setValueId(albumAttributeValueVo.getValueId());
				//为了循环多次执行循环insert语句
				//可以优化为批量插入  减少循环
				albumAttributeValueMapper.insert(albumAttributeValue);
			}
		}

	}
	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {
		return albumInfoMapper.selectList(new LambdaQueryWrapper<AlbumInfo>().eq(AlbumInfo::getUserId,userId).orderByDesc(AlbumInfo::getId).last(" limit 20"));
	}

	@Override
	public List<AlbumAttributeValue> findAlbumAttributeValue(Long albumId) {
		//	AlbumAttributeValue 这个对象中的名称不需要赋值. 只需要获取到 attribute_id value_id
		return albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,albumId));
	}

	@GuiGuCache(prefix = "albumStat:info:")
	@Override
	public AlbumStatVo getAlbumStatVo(Long albumId) {
		return albumInfoMapper.selectAlbumStat(albumId);
	}
}
